package com.Unidbg_hengdin.System_cm;

import com.alibaba.fastjson.util.IOUtils;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.Symbol;
import com.github.unidbg.arm.backend.Unicorn2Factory;
import com.github.unidbg.arm.context.RegisterContext;
import com.github.unidbg.debugger.BreakPointCallback;
import com.github.unidbg.file.FileResult;
import com.github.unidbg.file.IOResolver;
import com.github.unidbg.file.linux.AndroidFileIO;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.SystemPropertyHook;
import com.github.unidbg.linux.android.SystemPropertyProvider;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.file.SimpleFileIO;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.pointer.UnidbgPointer;

import java.io.File;

public class Study10_01 extends AbstractJni implements IOResolver {
    private final AndroidEmulator emulator;
    private final VM vm;

    private final Memory memory;

    private final Module module;

    private final boolean logging;

    private final DvmClass NativeHelperUtils;

    private final  String  hengdin = "hengdin";

    Study10_01(boolean logging ){

        this.logging = logging;
        emulator = AndroidEmulatorBuilder.for64Bit()
                .setProcessName("com.xiaojianbang.app")
                .addBackendFactory(new Unicorn2Factory(true))
                .build();

        memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23));

        emulator.getSyscallHandler().addIOResolver(this);
        //  -------------------------  systemPropertyHook ---------------------
        SystemPropertyHook systemPropertyHook = new SystemPropertyHook(emulator);
        systemPropertyHook.setPropertyProvider(new SystemPropertyProvider() {
            @Override
            public String getProperty(String key) {
                System.out.println(" systemProperty hooked key: " + key );
                return null;
            }
        });
        memory.addHookListener(systemPropertyHook);
        //  -------------------------  systemPropertyHook ---------------------



        vm = emulator.createDalvikVM();
        vm.setVerbose(logging);
        vm.setJni(this);

        DalvikModule dalvikModule = vm.loadLibrary(new File("unidbg-android/src/test/java/com/Unidbg_hengdin/System_cm/libxiaojianbang.so"), false);
        module = dalvikModule.getModule();


        NativeHelperUtils = vm.resolveClass("com/xiaojianbang/ndk/NativeHelper");


    }

    void destory(){
        IOUtils.close(emulator);
        if(logging){
            System.out.println("destory !");
        }
    }
    public static void main(String[] args){
        Study10_01 test = new Study10_01(true);
        test.callFun();
        test.destory();
    }
    void callFun(){
        env1();
        env2();
        env3();

    }

    public void env1(){
        int pid = emulator.getPid();
        System.out.println("current pid: " + pid);




//        emulator.set(hengdin, "env1");
//        emulator.set("PATH", "env1");

        Symbol setenv = module.findSymbolByName("setenv", true);
        setenv.call(emulator, "PATH", "xxx777", 0);
        setenv.call(emulator, hengdin, "xxx777", 0);



    }
    public void env2(){
        // 查看env1 中的设置是否生效
        String hengdinRes = emulator.get(hengdin);
        System.out.println("hengdin hengdinRes : " + hengdinRes );

        String pathRes = emulator.get("PATH");
        System.out.println("hengdin pathRes : " + pathRes);

//        // 测试 setenv
        Symbol getenv = module.findSymbolByName("getenv", true);

        long res =(long) getenv.call(emulator, "PATH");
        long res1 =(long) getenv.call(emulator, hengdin);



    }

    public void env3(){
        //        hook getenv
        emulator.attach().addBreakPoint(module.findSymbolByName("getenv").getAddress(), new BreakPointCallback() {
            @Override
            public boolean onHit(Emulator<?> emulator, long address) {
                RegisterContext context = emulator.getContext();
                UnidbgPointer pointerArg = context.getPointerArg(0);
                String key = pointerArg.getString(0);
                System.out.println("hengdin  getenv: " + key);
                return true;
            }
        });
        // 调用 getenv
        StringObject res = NativeHelperUtils.callStaticJniMethodObject(emulator, "readSomething();");
        System.out.println("md5_retval res : " + res.getValue());


    }



    @Override
    public FileResult resolve(Emulator emulator, String pathname, int oflags) {
        System.out.println("pathname -------------: " + pathname);
        if("/proc/self/maps".equals(pathname)){
            return FileResult.success(new SimpleFileIO(oflags,new File("F:\\unidbg-master\\unidbg-android\\src\\test\\java\\com\\Unidbg_hengdin\\filehandle\\maps"),pathname));
//            return FileResult.success(new ByteArrayFileIO(oflags, pathname,"hengdin test unidbg filehandler !".getBytes()));
        }
        return null;
    }
}
